package com.ruoyi.config;


import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.domain.WsResult;
import com.ruoyi.enums.ConnectDeviceTypeEnum;
import com.ruoyi.util.RedisManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.Session;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class WebSocketManager {

    private static final String PONG = "pong";
    public static final WebSocketManager INSTANCE = new WebSocketManager();


    /**
     *  用于存所有的连接服务的客户端，这个对象存储是安全的
     */
    private Map<Long, WebSocketUser> webSocketSet = new HashMap<>();

    /**
     *  用于存所有的连接用户信息
     */
//    private Map<Long, LoginUser> webSocketUserSet = new HashMap<>();

    private WebSocketManager() {}

    /**
     * 指定发送   DEMO为1个单独用户
     */
    public boolean sessionSend(Long userId, WsResult wsResult,ConnectDeviceTypeEnum type){
        boolean result = false;
        List<Session> session = null;
        synchronized (this) {
            WebSocketUser webSocketUser = webSocketSet.get(userId);

            if (webSocketUser != null) {
                session = webSocketUser.getSessionList(type);
            }
            if (session != null && session.size() != 0) {
                try {
                    for(Session temp : session){
                        temp.getBasicRemote().sendObject(wsResult);
                    }
                    result = true;
                } catch (Exception e) {
                    log.error("webSocket消息发送失败:" + e);
                }
            }
        }

        return result;
    }

    /**
     * 针对后台所有已经连接的用户全体发送
     */
    public boolean sendBroadcastMessage(WsResult wsResult) {
        for (WebSocketUser user : webSocketSet.values()) {
            try {
                List<Session> session = user.getSessionList(ConnectDeviceTypeEnum.PC);
                if(session != null && session.size() != 0){
                    for(Session temp : session){
                        temp.getBasicRemote().sendObject(wsResult);
                    }
                }
            } catch (Exception e) {
                log.error("webSocket消息全体发送失败:" + e);
            }
        }
        return true;
    }

    //获取所有在线人员信息
    public List<LoginUser> getAllOnlineUser(){
        List<LoginUser> list = new ArrayList<>();
        webSocketSet.forEach((k,v)->{
            LoginUser loginUser = v.getLoginUser();
            log.debug("当前在线用户ID为:" + k + "--用户名为: " + loginUser.getUsername());
            list.add(loginUser);
        });
        return list;
    }

    //添加Session会话
    void add(Long userId, Session session, LoginUser loginUser, ConnectDeviceTypeEnum typeEnum) {
        synchronized (this) {
            WebSocketUser webSocketUser = webSocketSet.get(userId);
            if (webSocketUser == null) {
                webSocketUser = new WebSocketUser(loginUser);
                webSocketSet.put(userId, webSocketUser);
            }

            webSocketUser.addSession(typeEnum,session);
        }
    }

    //移除某个用户的会话
    public void remove(Long userId, Session session) {
        synchronized (this) {
            WebSocketUser webSocketUser = webSocketSet.get(userId);
            if (webSocketUser != null) {
                webSocketUser.removeSession(session);
                if (webSocketUser.isEmpty()) {
                    webSocketSet.remove(userId);
                }
            }
        }
    }

    //返回当前连接所有用户数量
    public int size() {
        synchronized(this) {
            return webSocketSet.size();
        }
    }

    //返回指定用户连接数量
    public int size(Long userId) {
        synchronized(this) {
            WebSocketUser webSocketUser = webSocketSet.get(userId);
            if(webSocketUser == null) return 0;
            return webSocketUser.size();
        }
    }

    //查询某一个用户，某平台是否连接
    public boolean isConnect(Long userId,ConnectDeviceTypeEnum type){
        synchronized (this) {
            WebSocketUser webSocketUser = webSocketSet.get(userId);
            if(webSocketUser == null || webSocketUser.getSessionList(type) == null || webSocketUser.getSessionList(type).size() == 0){
                return false;
            }else{
                return true;
            }
        }
    }

    //对所有电脑端的连接进行推送告警
    public boolean sendWarnByDept(Long dept,WsResult wsResult){
        Map<Session,WebSocketUser> remove = new HashMap<>();
        for (WebSocketUser user : webSocketSet.values()) {
            try {
                Long tempDeptId = RedisManager.getCashUserDeptId(user.getLoginUser().getUserId(),user.getLoginUser().getDeptId()) == null ? user.getLoginUser().getDeptId() :  RedisManager.getCashUserDeptId(user.getLoginUser().getUserId(),user.getLoginUser().getDeptId());
                log.debug("发送部门为:" + tempDeptId);
                if(tempDeptId.equals(dept)){
                    List<Session> session = user.getSessionList(ConnectDeviceTypeEnum.PC);
                    for(Session temp : session){
                        if(temp.isOpen()){
                            temp.getBasicRemote().sendObject(wsResult);
                        }else{
                            remove.put(temp,user);
                        }
                    }
                    log.debug("发送完成，成功发送" + session.size() + "条连接");
                }
            } catch (Exception e) {
                log.error("webSocket消息发送机构全体失败 :" , e);
            }
        }
        //循环完成后进行清理连接
        for (Map.Entry<Session, WebSocketUser> entry : remove.entrySet()) {
            Session temp = entry.getKey();
            WebSocketUser user = entry.getValue();
            user.removeSession(temp);// 及时清理虚假连接
        }
        return true;
    }

}
